namespace ScrumSprintMonitor.UI.Wpf
{
	#region #using Directives

	using System;
	using System.Collections.Generic;
	using System.Linq;

	#endregion

	public class Trendline
	{
		private readonly IList<double> xAxisValues;
		private readonly IList<double> yAxisValues;
		private int count;
		private double xAxisValuesSum;
		private double xxSum;
		private double xySum;
		private double yAxisValuesSum;

		public Trendline(IList<double> yAxisValues, IList<double> xAxisValues)
		{
			this.yAxisValues = yAxisValues;
			this.xAxisValues = xAxisValues;
			Initialize();
		}

		public double Slope { get; private set; }
		public double Intercept { get; private set; }
		public double Start { get; private set; }
		public double End { get; private set; }

		private void Initialize()
		{
			this.count = this.yAxisValues.Count;
			this.yAxisValuesSum = this.yAxisValues.Sum();
			this.xAxisValuesSum = this.xAxisValues.Sum();
			this.xxSum = 0;
			this.xySum = 0;
			for (int i = 0; i < this.count; i++)
			{
				this.xySum += (this.xAxisValues[i] * this.yAxisValues[i]);
				this.xxSum += (this.xAxisValues[i] * this.xAxisValues[i]);
			}
			Slope = CalculateSlope();
			Intercept = CalculateIntercept();
			Start = CalculateStart(this.xAxisValues.First());
			End = CalculateEnd(this.xAxisValues.Last());
		}

		private double CalculateSlope()
		{
			try
			{
				return ((this.count * this.xySum) - (this.xAxisValuesSum * this.yAxisValuesSum)) /
				       ((this.count * this.xxSum) - (this.xAxisValuesSum * this.xAxisValuesSum));
			}
			catch (DivideByZeroException)
			{
				return 0.0;
			}
		}

		private double CalculateIntercept()
		{
			return (this.yAxisValuesSum - (Slope * this.xAxisValuesSum)) / this.count;
		}

		public double CalculateStart(double xValue)
		{
			return (Slope * xValue) + Intercept;
		}

		public double CalculateEnd(double xValue)
		{
			return (Slope * xValue) + Intercept;
		}
	}
}